// praxis/hardware/simulated_sensor.cc
#include "praxis/hardware/simulated_sensor.h"

#include "praxis/hardware/iactuator.h"  // Full definition needed for GetCurrentValue()

namespace praxis {
CSimulatedSensor::CSimulatedSensor(const std::string& name,
                                   const std::string& unit,
                                   double initial_value, double noise_amplitude)
    : name_(name),
      unit_(unit),
      current_value_(initial_value),
      noise_amplitude_(noise_amplitude),
      base_value_(initial_value) {}

const std::string& CSimulatedSensor::GetName() const { return name_; }

void CSimulatedSensor::LinkToActuator(std::shared_ptr<IActuator> actuator,
                                      double influence) {
  linked_actuator_ = actuator;
  actuator_influence_ = influence;
}

void CSimulatedSensor::Update() {
  double deterministic_value = base_value_;
  if (linked_actuator_) {
    // A simple linear physics model
    deterministic_value = base_value_ + (linked_actuator_->GetCurrentValue() *
                                         actuator_influence_);
  }

  // Add random noise for realism
  double noise =
      ((static_cast<double>(rand()) / RAND_MAX) - 0.5) * 2.0 * noise_amplitude_;
  current_value_ = deterministic_value + noise;
}

nlohmann::json CSimulatedSensor::GetValueAsJson() const {
  return {{"value", current_value_}, {"unit", unit_}};
}
}  // namespace praxis